<?php
declare (strict_types=1);

namespace app\api\controller;

use app\BaseController;
use app\lib\exception\BaseException;
use app\middleware\api\Auth;
use app\model\CouponUsers;
use app\model\Product;
use app\model\RecordIntegral;
use app\model\Users;
use app\validate\api\Burse;
use PayPal\Api\Amount;
use PayPal\Api\Payer;
use PayPal\Api\Payment;
use PayPal\Api\RedirectUrls;
use PayPal\Api\Transaction;
use PayPal\Auth\OAuthTokenCredential;
use PayPal\Exception\PayPalConnectionException;
use PayPal\Rest\ApiContext;
use app\model\Order;
use think\facade\Db;
use think\facade\Log;

class Pay extends BaseController
{

    protected $middleware = [
        Auth::class => ['except' => 'notify']
    ];

    /**
     * 分发支付
     * @return \think\response\Json
     * @throws BaseException
     */
    public function index()
    {
        (new \app\validate\api\Pay())->goCheck();
        $params = request()->param();
        $user = request()->userid;
        $order = Order::getOrder($params['order_id'], $user);
        //分发 钱包支付 or paypal
        $result = $params['pay_mode'] == Order::BOOKING ? $this->payPal($order, $user) : $this->wallet($order, $user);
        return $this->success($result);
    }



    /**
     * 充值钱包
     * @return \think\response\Json
     * @throws BaseException
     */
    public function burse()
    {
        (new Burse())->goCheck();
        $params = request()->param();
        $user = request()->userid;
        $params['name'] = 'coin';
        $params['id'] = 0;
        return $this->success($this->payPal($params, $user));
    }

    /**
     * paypal支付
     * @param $order
     * @param $type
     * @return string|null
     * @throws BaseException
     */
    private function payPal($order, $user)
    {
        $paypal = new ApiContext(new OAuthTokenCredential(config('params.paypal.clientId'), config('params.paypal.clientSecret')));
        $paypal->setConfig($this->payConfig());
        $payer = new Payer();
        $payer->setPaymentMethod('paypal');
        $amount = new Amount();
        $amount->setTotal($order['pay_price'])->setCurrency(config('params.paypal.Currency'));
        $transaction = new Transaction();
        $transaction->setAmount($amount)->setDescription($order['name']);
        $redirectUrls = new RedirectUrls();
        $redirectUrls->setCancelUrl(env('paypal.redirecturl') . "/api/pay/notify?success=false")
            ->setReturnUrl(env('paypal.redirecturl') . "/api/pay/notify?success=true&money={$order}&user={$user}&order_id={$order['id']}");
        $payment = new Payment();
        $payment->setIntent('sale')->setPayer($payer)->setTransactions([$transaction])->setRedirectUrls($redirectUrls);
        try {
            //支付并返回信息
            $payment->create($paypal);
            return $payment->getApprovalLink();
        } catch (PayPalConnectionException $ex) {
            //打印错误信息
            throw new BaseException(['msg' => $ex]);
        }
    }


    //钱包支付
    private function wallet($order, $user)
    {
        $userModel = Users::find($user);
        if ($userModel->wallet < $order['pay_price']) {
            throw new BaseException(['msg' => '錢包餘額不足！']);
        }
        Db::startTrans();
        try {
            Order::where('id', $order['id'])->update([
                'pay_mode' => Order::PROMPTLY,
                'status' => Order::STATUS_EXAMINE
            ]);
            $userModel->wallet -= $order['pay_price'];

            //增加積分
            $userModel->save();
            $this->incIntegrate($order,$user);

            event('SaleEvent',$this->ev($order));
            Db::commit();
            return 'OK';
        } catch (\Exception $e) {
            Db::rollback();
            throw new BaseException(['msg' => $e]);
        }
    }



    //回调
    public function notify()
    {
        $params = request()->param();
        $success = trim($params['success']);
        if ($success == 'false' && !isset($params['paymentId']) && !isset($params['PayerID'])) {
            Log::error('取消付款');
            return view('paymentCancel');
        }
        $paymentId = trim($params['paymentId']);
        $PayerID = trim($params['PayerID']);
        if (!isset($success, $paymentId, $PayerID)) {
            Log::error('支付失败');
            return view('paymentError');

        }

        if (!$params['order_id']) {
            return $this->incWallet($params['user'], $params['money']['pay_price']);
        }
           return $this->updateOrder($params['order_id'], $params['user']);
    }


    private function ev($order)
    {
        $arr=[];
        $data=[];
        foreach ($order['detail'] as $item){
            $arr['product_id']=$item->product_id;
            $arr['num']=$item->num;
            $arr['sale']=$item->price*$item->num;
            $data[]=$arr;
        }
        return $data;
    }

    /**
     * 修改用户钱包金额
     * @param $user
     * @param  $money
     * @return \think\response\View
     */
    private function incWallet($user,  $money)
    {
        Users::where('id', $user)->inc('wallet',intval($money))->update();
        return view('paymentSuccess');
    }

    /**
     * 修改订单状态
     * @param $order
     * @param $user
     * @return \think\response\View
     * @throws BaseException
     */
    private function updateOrder($order, $user)
    {

        $model=Order::find($order);
        $user=Users::find($user);
        Order::where('id',$order)->update(['status'=>Order::STATUS_EXAMINE]);
        $this->incIntegrate($order,$user);
        event('SaleEvent',$this->ev($model));
        $push=new GeTui();
        $push->pushMessageToSingle($user->client_id,'您有一個新訂單'.$model->order_no,$user->type);
        return view('paymentSuccess');
    }


    /**
     * 增加积分
     * @param $order
     * @param $user
     * @throws BaseException
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    private function incIntegrate($order, $user)
    {

        $userModel = Users::find($user);
        $model=Order::where('id',$order->id)->with('detail')->find()->toArray();
        $integral = Product::whereIn('id', array_column($model['detail'], 'product_id'))
            ->sum('integral');
        $userModel->integral+=$integral;
        $userModel->integral_ing+=$integral;
        $userModel->save();

        RecordIntegral::record($user,$integral,RecordIntegral::TYPE_P,RecordIntegral::STATUS_INC);
        //删除使用过的优惠券
        CouponUsers::where('users_id',$user)->where('coupon_id',$model['coupon_id'])->delete();
    }

    /**
     * 配置沙箱log
     * @return array
     */
    private function payConfig()
    {
        return [
            //这里很重要没上线用沙盒，上线用上线
            'mode' => config('params.paypal.mode'),
            //下面是日志配置
            'log.LogEnabled' => config('params.paypal.LogEnabled'),
            'log.FileName' => config('params.paypal.FileName'),
            'log.LogLevel' => config('params.paypal.LogLevel')
        ];
    }

}
